import axios from 'axios';
import {configChange} from "../Config"
import {addUrlParams, isDevelopment} from "@core/utils";
import {getItem} from "../services/LocalDataService";
import {getUserInfo, logout} from "./SecurityService";
import download from "downloadjs";
import React from 'react';
import CryptoJS from 'crypto-js';
import {showMessage} from "../reducer/MsgReducer.tsx";


let localToken: string, curLang: string;

configChange((config: any) => {
    localToken = config.localToken;
    curLang = config.localLang;
});

axios.defaults.timeout = 10000000;


axios.interceptors.request.use((config: any) => {
    let userInfo = getUserInfo() || {};
    let urlArr = config.url.split('?')
    let paramsStr = config.method == 'get' ? decodeURIComponent(urlArr[1]) : JSON.stringify(config.data);
    let sign = CryptoJS.HmacSHA256(paramsStr, CryptoJS.MD5(userInfo.accessToken + '_' + userInfo.id + '_KSGUMeNHU8ORy0JmTRydCjFcokuz9jHj').toString()).toString();
    const token = getItem(localToken);
    const lang = getItem(curLang);
    config.baseUrl = "";
    // config.data = JSON.stringify(config.data);
    config.headers = {
        "Content-Type": "application/json",
        "access-token": token,
        "language": lang,
        "sign": sign
    };
    return config;
}, (error: any) => {
    return Promise.reject(error);
});

axios.interceptors.response.use((response: any) => {
    if (response.data.code == "1" || response.data.code == "-1") {
        return Promise.resolve(response)
    } else if (response.data.code == "-2" || response.data.code === 500 || response.data.code === 401) {
        logout();
        return Promise.reject(response);
    } else {
        return Promise.reject(response);
    }
}, (error: any) => {
    return Promise.reject(error)
});

// @ts-ignore
const AxiosGetUrl: Function = (url: string) => {
    if (!url) {
        url = "";
    }
    // 需要加前缀
    if (url.substr(0, 1) === "/") {
        // 在开发环境且localStorage中有自定义的后台地址
        if (isDevelopment(true) && localStorage.backUrl) {
            url = localStorage.backUrl + url;
        }
    }
    return url;
};

// @ts-ignore
const AxiosSer: Function = (url: string, method: string, params?: object, isMessBool?: Boolean = false): Promise<unknown> => {
    method = method.toLocaleLowerCase();
    if (method === "get") {
        return AxiosGet(url, params)
    } else if (method === "post") {
        return AxiosPost(url, params, isMessBool)
    } else if (method === "patch") {
        return AxiosPatch(url, params)
    } else if (method === "put") {
        return AxiosPut(url, params, isMessBool)
    } else if (method === "delete") {
        return AxiosDelete(url, params)
    }
}

// @ts-ignore
const AxiosGet: Function = (url: string, params?: object): Promise<unknown> => {
    return new Promise((resolve: Function, reject: Function) => {
        axios.get(addUrlParams(AxiosGetUrl(url), {_: Math.random(), ...params}), {
            // params: params
        }).then((response: any) => {
            resolve(response.data);
        }).catch((error: any) => {
            reject(error);
        })
    }).catch((response: any) => {
        showMessage({
            type: "error",
            msg: response.data.msg
        })
        return response.data;
    })
};

// @ts-ignore
const AxiosPost: Function = (url: string, params?: object, isMessBool?: Boolean = false): Promise<unknown> => {
    return new Promise((resolve: Function, reject: Function) => {
        axios.post(AxiosGetUrl(url), params).then((response: any) => {
            resolve(response.data);
        }, (error: any) => {
            reject(error);
        })
    }).then((data: any) => {
        isMessBool && showMessage({
            type: "success",
            msg: data.msg
        })
        return data;
    }).catch((response: any) => {
        showMessage({
            type: "error",
            msg: response.data.msg
        })
        return response.data;
    });
};

// @ts-ignore
const AxiosPatch: Function = (url: string, params?: object): Promise<unknown> => {
    return new Promise((resolve: Function, reject: Function) => {
        axios.patch(AxiosGetUrl(url), params).then((response: any) => {
            resolve(response.data);
        }, (error: any) => {
            reject(error);
        })
    }).catch((response: any) => {
        showMessage({
            type: "error",
            msg: response.data.msg
        })
        return response.data;
    })
};

// @ts-ignore
const AxiosPut: Function = (url: string, params?: object, isMessBool: boolean = true): Promise<unknown> => {
    return new Promise((resolve: Function, reject: Function) => {
        axios.put(AxiosGetUrl(url), params).then((response: any) => {
            resolve(response.data);
        }, (error: any) => {
            reject(error);
        })
    }).then((data: any) => {
        isMessBool && data.code == 1 && showMessage({
            type: "success",
            msg: data.msg
        })
        return data;
    }).catch((response: any) => {
        isMessBool && showMessage({
            type: "error",
            msg: response.data.msg
        });
        return response.data;
    });
};

// @ts-ignore
const AxiosDelete: Function = (url: string, params?: object): Promise<unknown> => {
    return new Promise((resolve: Function, reject: Function) => {
        axios.delete(AxiosGetUrl(url), {data: params}).then((response: any) => {
            resolve(response.data);
        }, (error: any) => {
            reject(error);
        })
    }).then((data: any) => {
        data.code == 1 && showMessage({
            type: "success",
            msg: data.msg
        })
        return data;
    }).catch((response: any) => {
        showMessage({
            type: "error",
            msg: response.data.msg
        })
        return response.data;
    })
};
// @ts-ignore
const AxiosUpload: Function = (url: string, params: any, onProgress: Function, method: string = "POST") => {
    return new Promise((resolve: Function, reject: Function) => {
        let xhr: any = new XMLHttpRequest(),
            targetUrl: string = AxiosGetUrl(url);
        xhr.open(method, targetUrl);
        xhr.setRequestHeader("language", getItem(curLang));
        xhr.setRequestHeader("access-token", getItem(localToken));
        let obj: any = {}
        params.forEach((item: any, key: any) => {
            if (!(item instanceof File) && item) {
                obj[key] = item;
            }
        })
        let newObj: any = {}
        let sortedKeys = Object.keys(obj).sort();
        sortedKeys.forEach((key: any) => {
            newObj[key] = obj[key];
        })
        let userInfo = getUserInfo() || {};
        let sign = CryptoJS.HmacSHA256(JSON.stringify(newObj), CryptoJS.MD5(userInfo.accessToken + '_' + userInfo.id + '_KSGUMeNHU8ORy0JmTRydCjFcokuz9jHj').toString()).toString();
        xhr.setRequestHeader("sign", sign);
        xhr.onload = (res: any) => {
            try {
                let json = JSON.parse(res.target.responseText);
                if (json.code === "1" || json.code === "-1") {
                    return resolve(json)
                } else if (json.code === "-2" || json.code === 500) {
                    logout();
                    return reject(json);
                } else {
                    showMessage({
                        type: "error",
                        msg: json.msg
                    })
                    return reject(json);
                }
            } catch (e) {
                reject(e);
            }
        };
        xhr.onerror = reject;
        if (xhr.upload && onProgress) {
            xhr.upload.onprogress = function (e: any) {
                onProgress.call(this, e, xhr);
            };
        }
        xhr.send(params);
    });
};
// @ts-ignore
const AxiosDownload: Function = (url: string, params: any, onProgress: Function, method: string = "GET") => {
    return new Promise((resolve, reject) => {
        method = method.toLocaleLowerCase();
        let xhr: any = new XMLHttpRequest(),
            // 当url中有://协议说明是绝对地址 不需要加前缀
            targetUrl = method === "get" ? addUrlParams(AxiosGetUrl(url), params) : AxiosGetUrl(url);

        if (url.indexOf("://") !== -1) {
            targetUrl = url;
            xhr.open("GET", targetUrl, true);
        } else {
            xhr.open(method, targetUrl, true);
            // 只有本站加token
            xhr.setRequestHeader("language", getItem(curLang));
            xhr.setRequestHeader("access-token", getItem(localToken));
            xhr.setRequestHeader("content-type", "application/json");
            let urlArr = targetUrl.split('?')
            let userInfo = getUserInfo() || {};
            let sign = CryptoJS.HmacSHA256(decodeURIComponent(urlArr[1]), CryptoJS.MD5(userInfo.accessToken + '_' + userInfo.id + '_KSGUMeNHU8ORy0JmTRydCjFcokuz9jHj').toString()).toString()
            xhr.setRequestHeader("sign", sign);
            xhr.responseType = "blob";

            showMessage({
                type: "loading",
                msg: {
                    content: <div style={{width: '100px', height: '50px'}}>Loading ...</div>,
                    key: url,
                    duration: 100,
                    style: {
                        top: 0,
                        left: '50%',
                        position: 'fixed',
                    }
                }
            })
            xhr.addEventListener("progress", function (e: any) {
                showMessage({
                    type: "loading",
                    msg: {
                        content: <div style={{width: '100px', height: '50px'}}>Loading ...</div>,
                        key: url,
                        duration: 100,
                        style: {
                            top: 0,
                            left: '50%',
                            position: 'fixed',
                        }
                    }
                })
                onProgress && onProgress(e);
            });
            xhr.onload = function (e: any) {
                let blob: any = e.target.response;
                // 下载出错返回的是json数据
                if (blob.type === "application/json") {
                    // 将Blob数据转换为文本=>再转为对象
                    let reader: any = new FileReader();
                    reader.onload = () => {
                        try {
                            let json = JSON.parse(reader.result);
                            if (json.code === "1" || json.code === "-1") {
                                return resolve(json)
                            } else if (json.code === "-2" || json.code === 500) {
                                logout();
                                return reject(json);
                            } else {
                                showMessage({
                                    type: "destroy",
                                    msg: url
                                });
                                showMessage({
                                    type: "error",
                                    msg: json.msg
                                });
                                return reject(json);
                            }
                        } catch (e) {
                            reject(e);
                        }
                    };
                    reader.readAsText(blob);
                    return;
                }
                showMessage({
                    type: "destroy",
                    msg: url
                });
                let disposition = e.currentTarget.getResponseHeader("content-disposition"),
                    filename = disposition && disposition.match(/filename=(.*)/)[1];
                download(e.target.response, decodeURIComponent(filename ? filename.replace(new RegExp('"', 'g'), '') : ''));
                resolve();
            }
        }
        xhr.send(JSON.stringify(params));
    });
}

export {
    AxiosGetUrl,
    AxiosSer,
    AxiosGet,
    AxiosPost,
    AxiosPatch,
    AxiosPut,
    AxiosDelete,
    AxiosUpload,
    AxiosDownload
};